#include "GetDirectDraw.h"

#pragma comment(lib,"ddraw.lib")
#pragma comment(lib,"dxguid.lib")

LPDIRECTDRAW7 GetDirectDraw(void)
{
	LPDIRECTDRAW7 lpdd = NULL;
	if(FAILED(DirectDrawCreateEx(NULL,(LPVOID*)&lpdd,IID_IDirectDraw7,NULL)))
	{
		return NULL;
	}

	return lpdd;
}

void ReleaseDirectDraw(LPDIRECTDRAW7 &lpdd)
{
	if(!lpdd)
	{
		return;
	}
	lpdd->Release();
	lpdd = NULL;
}

LPDIRECTDRAWSURFACE7 GetDirectDrawSurface(LPDIRECTDRAW7 lpDD,bool bFullScreen)
{
	DDSURFACEDESC2	kddsd;
	memset(&kddsd,0,sizeof(kddsd));
	kddsd.dwSize = sizeof(kddsd);

	if(bFullScreen)
	{
		kddsd.dwBackBufferCount = 1;
		kddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
		kddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
	}
	else
	{

		kddsd.dwFlags = DDSD_CAPS;
		kddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	}

	LPDIRECTDRAWSURFACE7	pkDrawSurface7 = NULL;
	if(FAILED(lpDD->CreateSurface(&kddsd,&pkDrawSurface7,NULL)))
	{
		return NULL;
	}

	return pkDrawSurface7;
}

void ReleaseDirectDrawSurface(LPDIRECTDRAWSURFACE7 &lpDDSF)
{
	if(!lpDDSF)
	{
		return;
	}
	lpDDSF->Release();
	lpDDSF = NULL;
}

LPDIRECTDRAWSURFACE7 GetDirectDrawSurfaceBack(LPDIRECTDRAWSURFACE7 lpSurfacePrimary)
{
	LPDIRECTDRAWSURFACE7 lpSurfaceBack = NULL;
	DDSURFACEDESC2	kddsd;
	memset(&kddsd,0,sizeof(kddsd));
	kddsd.dwSize = sizeof(kddsd);
	kddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

	if(FAILED(lpSurfacePrimary->GetAttachedSurface(&kddsd.ddsCaps,&lpSurfaceBack)))
	{
		return NULL;
	}

	return lpSurfaceBack;
}

LPDIRECTDRAWSURFACE7 DirectDrawCreateSurface(LPDIRECTDRAW7 lpDD,int iWidth,int iHeight,int iMemFlag)
{
	DDSURFACEDESC2 ddsd;
	LPDIRECTDRAWSURFACE7 lpdds;

	DDRAW_INIT_STRUCT(ddsd);

	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
	ddsd.dwWidth = iWidth;
	ddsd.dwHeight = iHeight;
	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | iMemFlag;

	if(FAILED(lpDD->CreateSurface(&ddsd,&lpdds,NULL)))
	{
		return NULL;
	}

	DDCOLORKEY kColorKey;
	kColorKey.dwColorSpaceLowValue = 0;
	kColorKey.dwColorSpaceHighValue = 0;

	lpdds->SetColorKey(DDCKEY_SRCBLT,&kColorKey);

	return lpdds;
}

LPDIRECTDRAWPALETTE GetDirectDrawPalette(LPDIRECTDRAW7 lpDD)
{
	LPDIRECTDRAWPALETTE		pkDrawPalette = NULL;
	PALETTEENTRY      palette[256];
	for (int color=1; color < 255; color++)
	{
		palette[color].peRed   = rand()%256;
		palette[color].peGreen = rand()%256;
		palette[color].peBlue  = rand()%256;

		palette[color].peFlags = PC_NOCOLLAPSE;
	}

	palette[0].peRed   = 0;
	palette[0].peGreen = 0;
	palette[0].peBlue  = 0;
	palette[0].peFlags = PC_NOCOLLAPSE;

	palette[255].peRed   = 255;
	palette[255].peGreen = 255;
	palette[255].peBlue  = 255;
	palette[255].peFlags = PC_NOCOLLAPSE;

	if(FAILED(lpDD->CreatePalette(DDPCAPS_8BIT|
		DDPCAPS_ALLOW256|
		DDPCAPS_INITIALIZE,
		palette,&pkDrawPalette,NULL)))
	{
		return NULL;
	}

	return pkDrawPalette;
}

void ReleaseDirectDrawPalette(LPDIRECTDRAWPALETTE &lpDDPT)
{
	if(!lpDDPT)
	{
		return;
	}
	lpDDPT->Release();
	lpDDPT = NULL;
}

LPDIRECTDRAWCLIPPER DDRAWAttachClipper(LPDIRECTDRAW7 lpDD,LPDIRECTDRAWSURFACE7 lpdds,int iNumRects,LPRECT ClipList)
{
	LPDIRECTDRAWCLIPPER lpddClipper;
	LPRGNDATA lpRegionData;

	if(FAILED(lpDD->CreateClipper(0,&lpddClipper,NULL)))
	{
		return NULL;
	}

	lpRegionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + iNumRects * sizeof(RECT));

	memcpy(lpRegionData->Buffer,ClipList,sizeof(RECT) * iNumRects);

	lpRegionData->rdh.dwSize = sizeof(RGNDATAHEADER);
	lpRegionData->rdh.iType = RDH_RECTANGLES;
	lpRegionData->rdh.nCount = iNumRects;;
	lpRegionData->rdh.nRgnSize = iNumRects * sizeof(RECT);
	lpRegionData->rdh.rcBound.left = 64000;
	lpRegionData->rdh.rcBound.top = 64000;
	lpRegionData->rdh.rcBound.right = -64000;
	lpRegionData->rdh.rcBound.bottom = -64000;

	for(int i = 0;i < iNumRects;++i)
	{
		if(ClipList[i].left < lpRegionData->rdh.rcBound.left)
		{
			lpRegionData->rdh.rcBound.left = ClipList[i].left;
		}

		if(ClipList[i].top < lpRegionData->rdh.rcBound.top)
		{
			lpRegionData->rdh.rcBound.top = ClipList[i].top;
		}

		if(ClipList[i].right > lpRegionData->rdh.rcBound.right)
		{
			lpRegionData->rdh.rcBound.right = ClipList[i].right;
		}

		if(ClipList[i].bottom > lpRegionData->rdh.rcBound.bottom)
		{
			lpRegionData->rdh.rcBound.bottom = ClipList[i].bottom;
		}
	}

	if(FAILED(lpddClipper->SetClipList(lpRegionData,0)))
	{
		free(lpRegionData);
		return NULL;
	}

	if(FAILED(lpdds->SetClipper(lpddClipper)))
	{
		free(lpRegionData);
		return NULL;
	}

	free(lpRegionData);
	return lpddClipper;
}

void ReleaseDirectDrawClipper(LPDIRECTDRAWCLIPPER& lpClipper)
{
	if(!lpClipper)
	{
		return;
	}

	lpClipper->Release();
	lpClipper = NULL;
}

int DirectDrawTextGDI(const WCHAR* acText,int iX,int iY,COLORREF Color,LPDIRECTDRAWSURFACE7 lpdds)
{
	HDC hXdc;

	if(FAILED(lpdds->GetDC(&hXdc)))
	{
		return 0;
	}

	SetTextColor(hXdc,Color);
	SetBkMode(hXdc,TRANSPARENT);

	TextOut(hXdc,iX,iY,acText,wcslen(acText));
	lpdds->ReleaseDC(hXdc);
	return 1;
}

UINT* DDrawLockSurface(LPDIRECTDRAWSURFACE7 lpdds,int& lPitch)
{
	DDSURFACEDESC2 kDD;
	DDRAW_INIT_STRUCT(kDD);
	if(FAILED(lpdds->Lock(NULL,&kDD,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL)))
	{
		return NULL;
	}

	lPitch = int(kDD.lPitch >> 2);
	return (UINT*)kDD.lpSurface;
}

bool DDrawUnlockSurface(LPDIRECTDRAWSURFACE7 lpdds)
{
	if(FAILED(lpdds->Unlock(NULL)))
	{
		return false;
	}

	return true;
}